﻿using System;
using OpenTK.Graphics.OpenGL4;

namespace Painter3D.RenderSys.RenderObject
{
    /// <summary>
    /// 使用索引绘制模式的顶点数据
    /// </summary>
    public class ElementVertexData : VertexData
    {
        /// <summary>
        /// 描述该顶点数据期望的绘制图元模式
        /// </summary>
        readonly public BeginMode shadpeType;
        /// <summary>
        /// 预期绘制的顶点数量
        /// </summary>
        protected int drawSize;
        /// <summary>
        /// 实际包含的顶点信息组个数
        /// </summary>
        readonly protected int pointSize;
        /// <summary>
        /// EBO句柄
        /// </summary>
        readonly protected int EBO;

        /// <summary>
        /// 构造使用索引绘制的顶点数据对象，该对象只有位置信息
        /// </summary>
        /// <param name="position">顶点位置数据数组</param>
        /// <param name="index">索引</param>
        /// <param name="shadpeType">图元类型</param>
        public ElementVertexData(float[] position, uint[] index, BeginMode shadpeType = BeginMode.Triangles) : base(position)
        {
            this.shadpeType = shadpeType;
            drawSize = index.Length;
            EBO = GL.GenBuffer();
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, EBO);
            GL.BufferData(BufferTarget.ElementArrayBuffer, index.Length * sizeof(uint), index, BufferUsageHint.StaticDraw);
        }
        /// <summary>
        /// 构造使用索引绘制的顶点数据对象，该对象只有位置和UV1信息
        /// </summary>
        /// <param name="position">顶点位置数据数组</param>
        /// <param name="UV">顶点UV坐标数组</param>
        /// <param name="index">索引</param>
        /// <param name="shadpeType">图元类型</param>
        public ElementVertexData(float[] position, float[] UV, uint[] index, BeginMode shadpeType = BeginMode.Triangles) : base(position, UV)
        {
            this.shadpeType = shadpeType;
            drawSize = index.Length;
            EBO = GL.GenBuffer();
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, EBO);
            GL.BufferData(BufferTarget.ElementArrayBuffer, index.Length * sizeof(uint), index, BufferUsageHint.StaticDraw);
        }


        /// <summary>
        /// 构造使用索引绘制的顶点数据对象，必须包含位置信息，并放置于第一组
        /// </summary>
        /// <param name="requests">顶点请求数据数组</param>
        /// <param name="datas">数据列表</param>
        /// <param name="index">绘制索引</param>
        /// <param name="shadpeType">图元类型</param>
        public ElementVertexData(ShaderInfo.VertexRequestTagEnum[] requests, float[][] datas, uint[] index, BeginMode shadpeType = BeginMode.Triangles, BufferUsageHint hint = BufferUsageHint.StaticDraw) : base(requests, datas, hint)
        {
            this.shadpeType = shadpeType;
            drawSize = index.Length;
            EBO = GL.GenBuffer();
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, EBO);
            GL.BufferData(BufferTarget.ElementArrayBuffer, index.Length * sizeof(uint), index, hint);
        }

        /// <summary>
        /// 重新传递索引数组
        /// </summary>
        /// <param name="index">索引信息</param>
        public void Reload(uint[] index)
        {
            drawSize = index.Length;
            GL.BindVertexArray(VAO);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, EBO);
            GL.BufferSubData(BufferTarget.ElementArrayBuffer, (IntPtr)0, index.Length * sizeof(uint), index);
        }

        public override void DrawData()
        {
            GL.BindVertexArray(VAO);
            GL.DrawElements(shadpeType, drawSize, DrawElementsType.UnsignedInt, 0);
        }

        #region Dispose
        protected override void Dispose(bool manule)
        {
            if (manule)
            {
                GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
                GL.DeleteBuffer(EBO);
            }
            base.Dispose(manule);
        }
        #endregion
    }
}
